// 调试工具集合

// 日志级别
export enum LogLevel {
  DEBUG = 0,
  INFO = 1,
  WARN = 2,
  ERROR = 3,
  NONE = 4,
}

// 日志配置
interface LogConfig {
  level: LogLevel
  enableConsole: boolean
  enableStorage: boolean
  maxStorageSize: number
  enableRemote: boolean
  remoteUrl?: string
  enableTimestamp: boolean
  enableCaller: boolean
}

// 日志条目
interface LogEntry {
  level: LogLevel
  message: string
  data?: any
  timestamp: number
  caller?: string
  stack?: string
}

// 调试面板配置
interface DebugPanelConfig {
  position: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
  theme: 'light' | 'dark'
  maxLogs: number
  enableFilters: boolean
  enableSearch: boolean
}

// 日志管理器类
class LogManager {
  private config: LogConfig = {
    level: LogLevel.DEBUG,
    enableConsole: true,
    enableStorage: true,
    maxStorageSize: 1000,
    enableRemote: false,
    enableTimestamp: true,
    enableCaller: true,
  }

  private logs: LogEntry[] = []
  private storageKey = 'debug_logs'

  constructor() {
    this.loadLogsFromStorage()
  }

  // 更新配置
  updateConfig(config: Partial<LogConfig>): void {
    this.config = { ...this.config, ...config }
  }

  // 获取调用者信息
  private getCaller(): string {
    if (!this.config.enableCaller) return ''

    try {
      const stack = new Error().stack
      if (stack) {
        const lines = stack.split('\n')
        // 跳过 Error 和 getCaller 本身
        const callerLine = lines[3]
        if (callerLine) {
          const match = callerLine.match(/at\s+(.+?)\s+\((.+?):(\d+):(\d+)\)/)
          if (match) {
            return `${match[1]} (${match[2]}:${match[3]})`
          }
        }
      }
    } catch (error) {
      // 忽略错误
    }

    return ''
  }

  // 记录日志
  private log(level: LogLevel, message: string, data?: any): void {
    if (level < this.config.level) return

    const entry: LogEntry = {
      level,
      message,
      data,
      timestamp: this.config.enableTimestamp ? Date.now() : 0,
      caller: this.getCaller(),
    }

    // 添加到内存
    this.logs.push(entry)

    // 限制内存中的日志数量
    if (this.logs.length > this.config.maxStorageSize) {
      this.logs = this.logs.slice(-this.config.maxStorageSize)
    }

    // 控制台输出
    if (this.config.enableConsole) {
      this.outputToConsole(entry)
    }

    // 保存到本地存储
    if (this.config.enableStorage) {
      this.saveLogsToStorage()
    }

    // 远程上报
    if (this.config.enableRemote && this.config.remoteUrl) {
      this.sendToRemote(entry)
    }
  }

  // 控制台输出
  private outputToConsole(entry: LogEntry): void {
    const timestamp = this.config.enableTimestamp
      ? `[${new Date(entry.timestamp).toLocaleTimeString()}] `
      : ''

    const caller = entry.caller ? ` [${entry.caller}]` : ''
    const prefix = `${timestamp}[${LogLevel[entry.level]}]${caller}`

    switch (entry.level) {
      case LogLevel.DEBUG:
        console.debug(prefix, entry.message, entry.data || '')
        break
      case LogLevel.INFO:
        console.info(prefix, entry.message, entry.data || '')
        break
      case LogLevel.WARN:
        console.warn(prefix, entry.message, entry.data || '')
        break
      case LogLevel.ERROR:
        console.error(prefix, entry.message, entry.data || '')
        break
    }
  }

  // 保存到本地存储
  private saveLogsToStorage(): void {
    try {
      const logsToSave = this.logs.slice(-this.config.maxStorageSize)
      uni.setStorageSync(this.storageKey, JSON.stringify(logsToSave))
    } catch (error) {
      console.error('Failed to save logs to storage:', error)
    }
  }

  // 从本地存储加载
  private loadLogsFromStorage(): void {
    try {
      const stored = uni.getStorageSync(this.storageKey)
      if (stored) {
        this.logs = JSON.parse(stored)
      }
    } catch (error) {
      console.error('Failed to load logs from storage:', error)
    }
  }

  // 发送到远程服务器
  private async sendToRemote(entry: LogEntry): Promise<void> {
    try {
      await uni.request({
        url: this.config.remoteUrl!,
        method: 'POST',
        data: {
          ...entry,
          platform: this.getPlatform(),
          userAgent: this.getUserAgent(),
        },
      })
    } catch (error) {
      // 静默失败
    }
  }

  // 获取平台信息
  private getPlatform(): string {
    // #ifdef H5
    return 'H5'
    // #endif
    // #ifdef MP-WEIXIN
    return 'MP-WEIXIN'
    // #endif
    // #ifdef MP-ALIPAY
    return 'MP-ALIPAY'
    // #endif
    // #ifdef MP-BAIDU
    return 'MP-BAIDU'
    // #endif
    // #ifdef MP-TOUTIAO
    return 'MP-TOUTIAO'
    // #endif
    // #ifdef APP-PLUS
    return 'APP-PLUS'
    // #endif
    return 'UNKNOWN'
  }

  // 获取用户代理
  private getUserAgent(): string {
    // #ifdef H5
    return navigator.userAgent
    // #endif
    return ''
  }

  // 公共日志方法
  debug(message: string, data?: any): void {
    this.log(LogLevel.DEBUG, message, data)
  }

  info(message: string, data?: any): void {
    this.log(LogLevel.INFO, message, data)
  }

  warn(message: string, data?: any): void {
    this.log(LogLevel.WARN, message, data)
  }

  error(message: string, data?: any): void {
    this.log(LogLevel.ERROR, message, data)
  }

  // 获取日志
  getLogs(level?: LogLevel, limit?: number): LogEntry[] {
    let filteredLogs = this.logs

    if (level !== undefined) {
      filteredLogs = filteredLogs.filter((log) => log.level >= level)
    }

    if (limit) {
      filteredLogs = filteredLogs.slice(-limit)
    }

    return filteredLogs
  }

  // 清空日志
  clearLogs(): void {
    this.logs = []
    uni.removeStorageSync(this.storageKey)
  }

  // 导出日志
  exportLogs(): string {
    return JSON.stringify(this.logs, null, 2)
  }

  // 获取日志统计
  getLogStats(): Record<string, number> {
    const stats: Record<string, number> = {}

    Object.values(LogLevel).forEach((level) => {
      if (typeof level === 'string') {
        stats[level] = this.logs.filter(
          (log) => log.level === LogLevel[level as keyof typeof LogLevel]
        ).length
      }
    })

    return stats
  }
}

// 调试面板类
class DebugPanel {
  private config: DebugPanelConfig = {
    position: 'bottom-right',
    theme: 'dark',
    maxLogs: 100,
    enableFilters: true,
    enableSearch: true,
  }

  private isVisible = false
  private panelElement: HTMLElement | null = null
  private logManager: LogManager

  constructor(logManager: LogManager) {
    this.logManager = logManager
  }

  // 更新配置
  updateConfig(config: Partial<DebugPanelConfig>): void {
    this.config = { ...this.config, ...config }
  }

  // 显示调试面板
  show(): void {
    // #ifdef H5
    if (typeof window === 'undefined') return

    if (!this.panelElement) {
      this.createPanel()
    }

    this.panelElement!.style.display = 'block'
    this.isVisible = true
    this.updateLogs()
    // #endif
  }

  // 隐藏调试面板
  hide(): void {
    // #ifdef H5
    if (this.panelElement) {
      this.panelElement.style.display = 'none'
      this.isVisible = false
    }
    // #endif
  }

  // 切换显示状态
  toggle(): void {
    if (this.isVisible) {
      this.hide()
    } else {
      this.show()
    }
  }

  // 创建面板元素
  private createPanel(): void {
    // #ifdef H5
    if (typeof window === 'undefined') return

    const panel = document.createElement('div')
    panel.id = 'debug-panel'
    panel.style.cssText = `
      position: fixed;
      ${this.config.position.includes('top') ? 'top: 10px;' : 'bottom: 10px;'}
      ${this.config.position.includes('left') ? 'left: 10px;' : 'right: 10px;'}
      width: 400px;
      height: 300px;
      background: ${this.config.theme === 'dark' ? '#1a1a1a' : '#ffffff'};
      color: ${this.config.theme === 'dark' ? '#ffffff' : '#000000'};
      border: 1px solid ${this.config.theme === 'dark' ? '#333' : '#ddd'};
      border-radius: 8px;
      box-shadow: 0 4px 12px rgba(0,0,0,0.3);
      z-index: 9999;
      font-family: monospace;
      font-size: 12px;
      display: none;
      flex-direction: column;
    `

    // 创建头部
    const header = document.createElement('div')
    header.style.cssText = `
      padding: 8px 12px;
      border-bottom: 1px solid ${
        this.config.theme === 'dark' ? '#333' : '#ddd'
      };
      display: flex;
      justify-content: space-between;
      align-items: center;
      background: ${this.config.theme === 'dark' ? '#2a2a2a' : '#f5f5f5'};
    `

    const title = document.createElement('div')
    title.textContent = 'Debug Panel'
    title.style.fontWeight = 'bold'

    const closeBtn = document.createElement('button')
    closeBtn.textContent = '×'
    closeBtn.style.cssText = `
      background: none;
      border: none;
      color: inherit;
      font-size: 16px;
      cursor: pointer;
      padding: 0;
      width: 20px;
      height: 20px;
    `
    closeBtn.onclick = () => this.hide()

    header.appendChild(title)
    header.appendChild(closeBtn)

    // 创建工具栏
    const toolbar = document.createElement('div')
    toolbar.style.cssText = `
      padding: 8px 12px;
      border-bottom: 1px solid ${
        this.config.theme === 'dark' ? '#333' : '#ddd'
      };
      display: flex;
      gap: 8px;
      align-items: center;
    `

    const clearBtn = document.createElement('button')
    clearBtn.textContent = 'Clear'
    clearBtn.style.cssText = `
      background: #ff4757;
      color: white;
      border: none;
      padding: 4px 8px;
      border-radius: 4px;
      cursor: pointer;
      font-size: 11px;
    `
    clearBtn.onclick = () => {
      this.logManager.clearLogs()
      this.updateLogs()
    }

    const exportBtn = document.createElement('button')
    exportBtn.textContent = 'Export'
    exportBtn.style.cssText = `
      background: #3742fa;
      color: white;
      border: none;
      padding: 4px 8px;
      border-radius: 4px;
      cursor: pointer;
      font-size: 11px;
    `
    exportBtn.onclick = () => {
      const logs = this.logManager.exportLogs()
      const blob = new Blob([logs], { type: 'application/json' })
      const url = URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = url
      a.download = `debug-logs-${Date.now()}.json`
      a.click()
      URL.revokeObjectURL(url)
    }

    toolbar.appendChild(clearBtn)
    toolbar.appendChild(exportBtn)

    // 创建日志容器
    const logContainer = document.createElement('div')
    logContainer.id = 'debug-log-container'
    logContainer.style.cssText = `
      flex: 1;
      overflow-y: auto;
      padding: 8px;
      font-size: 11px;
      line-height: 1.4;
    `

    panel.appendChild(header)
    panel.appendChild(toolbar)
    panel.appendChild(logContainer)

    document.body.appendChild(panel)
    this.panelElement = panel
    // #endif
  }

  // 更新日志显示
  private updateLogs(): void {
    // #ifdef H5
    if (!this.panelElement) return

    const container = this.panelElement.querySelector(
      '#debug-log-container'
    ) as HTMLElement
    if (!container) return

    const logs = this.logManager.getLogs(undefined, this.config.maxLogs)

    container.innerHTML = logs
      .map((log) => {
        const level = LogLevel[log.level]
        const time = new Date(log.timestamp).toLocaleTimeString()
        const caller = log.caller ? ` [${log.caller}]` : ''

        return `
        <div style="
          margin-bottom: 4px;
          padding: 2px 4px;
          border-radius: 3px;
          background: ${this.getLevelColor(log.level)};
        ">
          <span style="color: #666;">[${time}]</span>
          <span style="color: ${this.getLevelTextColor(
            log.level
          )}; font-weight: bold;">[${level}]</span>
          <span style="color: #999;">${caller}</span>
          <span>${log.message}</span>
          ${
            log.data
              ? `<div style="color: #666; margin-top: 2px;">${JSON.stringify(
                  log.data,
                  null,
                  2
                )}</div>`
              : ''
          }
        </div>
      `
      })
      .join('')
    // #endif
  }

  // 获取级别颜色
  private getLevelColor(level: LogLevel): string {
    switch (level) {
      case LogLevel.DEBUG:
        return 'rgba(0, 123, 255, 0.1)'
      case LogLevel.INFO:
        return 'rgba(40, 167, 69, 0.1)'
      case LogLevel.WARN:
        return 'rgba(255, 193, 7, 0.1)'
      case LogLevel.ERROR:
        return 'rgba(220, 53, 69, 0.1)'
      default:
        return 'transparent'
    }
  }

  // 获取级别文字颜色
  private getLevelTextColor(level: LogLevel): string {
    switch (level) {
      case LogLevel.DEBUG:
        return '#007bff'
      case LogLevel.INFO:
        return '#28a745'
      case LogLevel.WARN:
        return '#ffc107'
      case LogLevel.ERROR:
        return '#dc3545'
      default:
        return '#666'
    }
  }
}

// 性能监控工具
class PerformanceMonitor {
  private timers: Map<string, number> = new Map()
  private measures: Map<string, number> = new Map()

  // 开始计时
  start(name: string): void {
    this.timers.set(name, performance.now())
  }

  // 结束计时
  end(name: string): number {
    const startTime = this.timers.get(name)
    if (!startTime) {
      console.warn(`Timer "${name}" not found`)
      return 0
    }

    const duration = performance.now() - startTime
    this.measures.set(name, duration)
    this.timers.delete(name)

    return duration
  }

  // 测量函数执行时间
  measure<T>(name: string, fn: () => T): T {
    this.start(name)
    const result = fn()
    this.end(name)
    return result
  }

  // 异步测量函数执行时间
  async measureAsync<T>(name: string, fn: () => Promise<T>): Promise<T> {
    this.start(name)
    const result = await fn()
    this.end(name)
    return result
  }

  // 获取性能报告
  getReport(): Record<string, number> {
    return Object.fromEntries(this.measures)
  }

  // 清空记录
  clear(): void {
    this.timers.clear()
    this.measures.clear()
  }
}

// 创建全局实例
export const logManager = new LogManager()
export const debugPanel = new DebugPanel(logManager)
export const performanceMonitor = new PerformanceMonitor()

// 便捷方法
export const debug = logManager.debug.bind(logManager)
export const info = logManager.info.bind(logManager)
export const warn = logManager.warn.bind(logManager)
export const error = logManager.error.bind(logManager)

// 调试面板控制
export const showDebugPanel = debugPanel.show.bind(debugPanel)
export const hideDebugPanel = debugPanel.hide.bind(debugPanel)
export const toggleDebugPanel = debugPanel.toggle.bind(debugPanel)

// 性能监控
export const startTimer = performanceMonitor.start.bind(performanceMonitor)
export const endTimer = performanceMonitor.end.bind(performanceMonitor)
export const measure = performanceMonitor.measure.bind(performanceMonitor)
export const measureAsync =
  performanceMonitor.measureAsync.bind(performanceMonitor)

// 开发环境下的全局调试对象
// #ifdef H5
if (typeof window !== 'undefined') {
  ;(window as any).debug = {
    log: logManager,
    panel: debugPanel,
    performance: performanceMonitor,
    show: showDebugPanel,
    hide: hideDebugPanel,
    toggle: toggleDebugPanel,
  }
}
// #endif

export default {
  logManager,
  debugPanel,
  performanceMonitor,
  debug,
  info,
  warn,
  error,
  showDebugPanel,
  hideDebugPanel,
  toggleDebugPanel,
  startTimer,
  endTimer,
  measure,
  measureAsync,
}
